package com.semlab.server.enrichment;

import java.util.ArrayList;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.semlab.server.graph.ConceptRepository;
import com.semlab.server.graph.Neo4jTemplate;
import com.semlab.server.resources.Concept;
import com.semlab.server.resources.RelationshipTypes;

@Component
public class UpdateConceptsService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    DBpediaExtractor dbpedia;

    @Autowired
    ConceptRepository concepts;

    @Autowired
    Neo4jTemplate template;

    @Autowired
    IMDB imdb;

    public void process() {
        // get concept from neo4j
        template.beginTransaction();
        Concept concept = concepts.getNextConceptToUpdate();

        if (concept != null) {
            do {
                updateConcept(concept);
                concept = concepts.getNextConceptToUpdate();
            } while (concept != null);
            log.debug("writing changes");
            log.debug("updated all concepts");
        } else {
            log.debug("No concepts to update in queue");
        }
        template.finishTransaction();

    }

    public void updateConcept(Concept concept) {
        log.debug("trying to get concept uri {}", concept);
        Concept dbconcept = getUriFromDB(concept);
        imdb.updateMovieImdb(dbconcept);
        if (dbconcept.getUri() != null) {
            log.debug("found uri! {}", dbconcept.getUri());
            concepts.persist(dbconcept);
            concepts.assignConceptForEnrichment(dbconcept);
        } else {
            log.debug("uri not found {}");
            concept.changeDateUpdated();
            concept.incrementUriCounter();
            if (concept.getUriCounter() < ConceptRepository.UPDATE_LIMIT) {
                concepts.assignConceptForUpdate(concept);
            } else {
                concept.setEnriched(true);
            }
            concepts.persist(concept);
        }
    }

    private Concept getUriFromDB(Concept concept) {
        Concept dbconcept = dbpedia.chooseBestUri(concept);
        if (dbconcept != null) {

            // search by uri
            Node inIndex = concepts.getConceptByUri(dbconcept.getUri());
            Node dbnode = null;
            if (inIndex == null) {
                dbnode = concepts.persist(dbconcept);
            } else {
                // concept already exist, connect it for profiles
                dbnode = concepts.persist(dbconcept);
                ArrayList<Node> nodes = template.getNodesByRelationship(dbnode,
                        RelationshipTypes.LIKES, Direction.INCOMING, true);
                for (Node node : nodes) {
                    template.relate(node, inIndex, RelationshipTypes.LIKES);
                }
            }
            return dbconcept;
        }
        return concept;
    }

}
